<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    
</body>
<script>
    // 1.模块模式：创建私有变量和方法
    const module = (function() {
        let privateVar = 0;
        return {
            increment: function() { privateVar++; },
            getValue: function() { return privateVar; }
        };
    })();

    // 2.函数工厂：创建具有特定行为的函数

    function makeAdder(x) {
        return function(y) {
            return x + y;
        };
    }

    // 3. 防抖（Debounce）与节流（Throttle）
        // 防抖
        function debounce(fn, delay) {
            let timer;
            return function(...args) {
                clearTimeout(timer);
                timer = setTimeout(() => {
                    fn.apply(this, args);
                }, delay);
            };
        }

        // 节流
        function throttle(fn, interval) {
            let lastTime = 0;
            return function(...args) {
                const now = Date.now();
                if (now - lastTime >= interval) {
                    fn.apply(this, args);
                    lastTime = now;
                }
            };
        }

        window.addEventListener('resize', debounce(function() {
            console.log('Window resized');
        }, 200));

    // 4. 迭代器和生成器模拟
    function makeIterator(array) {
        let index = 0;
        
        return {
            next: function() {
                return index < array.length ? 
                    { value: array[index++], done: false } : 
                    { done: true };
            }
        };
    }

    const it = makeIterator(['a', 'b', 'c']);
    console.log(it.next().value); // 'a'
    console.log(it.next().value); // 'b'
    console.log(it.next().value); // 'c'
    console.log(it.next().done);  // true


    // 5. 柯里化（Currying）
        // 闭包可以实现函数的柯里化，将多参数函数转换为一系列单参数函数。
        function curry(fn) {
            return function curried(...args) {
                if (args.length >= fn.length) {
                    return fn.apply(this, args);
                } else {
                    return function(...args2) {
                        return curried.apply(this, args.concat(args2));
                    };
                }
            };
        }

        function sum(a, b, c) {
            return a + b + c;
        }

        const curriedSum = curry(sum);
        console.log(curriedSum(1)(2)(3)); // 6
        console.log(curriedSum(1, 2)(3)); // 6
</script>
</html>